package com.gin.kotlin.no_gay_alliance.activity

import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Rect
import android.os.Message
import android.os.Parcelable
import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.gin.kotlin.no_gay_alliance.R
import com.gin.kotlin.no_gay_alliance.app.App
import com.gin.kotlin.no_gay_alliance.argument.AttachmentArgument
import com.gin.kotlin.no_gay_alliance.argument.PostPrepareArgument
import com.gin.kotlin.no_gay_alliance.argument.PostPrepareArgument.Action
import com.gin.kotlin.no_gay_alliance.argument.UploadArgument
import com.gin.kotlin.no_gay_alliance.base.AbstractBindingActivity
import com.gin.kotlin.no_gay_alliance.base.AlertDialogUtils
import com.gin.kotlin.no_gay_alliance.base.FragmentStateContainer
import com.gin.kotlin.no_gay_alliance.base.InputMethodUtils
import com.gin.kotlin.no_gay_alliance.database.entity.EmojiHistory
import com.gin.kotlin.no_gay_alliance.database.entity.PostDraft
import com.gin.kotlin.no_gay_alliance.databinding.ActivityPostBinding
import com.gin.kotlin.no_gay_alliance.databinding.DialogPostOptionBinding
import com.gin.kotlin.no_gay_alliance.enums.HandlerMessageWhat
import com.gin.kotlin.no_gay_alliance.fragment.post.PostAttachmentFragment
import com.gin.kotlin.no_gay_alliance.fragment.post.PostBbsCodeFragment
import com.gin.kotlin.no_gay_alliance.fragment.post.PostEmojiFragment
import com.gin.kotlin.no_gay_alliance.fragment.post.PostTopicKeyFragment
import com.gin.kotlin.no_gay_alliance.model.AttachmentModel
import com.gin.kotlin.no_gay_alliance.model.PostAddTextModel
import com.gin.kotlin.no_gay_alliance.model.emoji.GenericEmojiModel
import com.gin.kotlin.no_gay_alliance.store.GlobalProperty
import com.gin.nga.api.PostApi
import com.gin.nga.callback.NgaCallback
import com.gin.nga.enums.ImageThumb
import com.gin.nga.enums.param.Hidden
import com.gin.nga.enums.param.PostAction
import com.gin.nga.enums.param.PostOption
import com.gin.nga.response.base.NgaResponse
import com.gin.nga.response.post.PrepareBody
import com.gin.nga.response.post.UploadBody
import com.gin.nga.utils.IAttach
import com.gin.nga.utils.NgaLocation
import com.gin.nga.utils.PostParamBuilder
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.parcelize.Parcelize
import retrofit2.Call
import retrofit2.Response
import java.time.ZonedDateTime
import java.util.regex.Pattern

/**
 * 发帖活动
 * @property forumId 版面ID，准备结束时获得值，用于查询主题分类
 * @property tabLayoutMediator TabLayoutMediator
 * @property postParamBuilder PostParamBuilder
 * @property api PostApi
 * @property argument PostPrepareArgument
 * @property bottomToolFragments 底部工具标签
 * @property sending 是否正在发帖
 * @property flagSuccess 成功标记
 */
class PostActivity : AbstractBindingActivity<ActivityPostBinding>(), TabLayoutMediator.TabConfigurationStrategy, TabLayout.OnTabSelectedListener {
    private var forumId: Long? = null
    private lateinit var attachmentArgument: AttachmentArgument
    private lateinit var uploadArgument: UploadArgument
    private lateinit var tabLayoutMediator: TabLayoutMediator
    private lateinit var postParamBuilder: PostParamBuilder
    private lateinit var api: PostApi
    private lateinit var argument: PostPrepareArgument
    private lateinit var bottomToolFragments: List<FragmentStateContainer>
    private var sending = false
    private var flagSuccess = false
    private var attachments: List<UploadBody>? = null

    override fun onPause() {
        super.onPause()

        val dao = App.INSTANCE.database.postDraftDao()
        val uuid = obtainPostDraftUuid(argument)
        if (flagSuccess) {
            // 清空草稿
            dao.del(uuid)
        } else {
            // 保存草稿
            val b = this.b ?: return
            b.etContent.text.toString().takeIf { it.isNotEmpty() }?.also { dao.add(PostDraft(uuid, ZonedDateTime.now(), b.etTitle.text.toString(), it)) }
        }
    }

    /**
     * onCreate方法的后续操作，如 [AbstractBindingActivity.registerLauncher]， 或 [AbstractBindingActivity.attachTabLayout]
     */
    override fun onCreate() {
        val b = this.b ?: return

        this.api = App.INSTANCE.ngaApi.postApi

        // 如果为引用模式，显示警告
        if (this.argument.action == Action.QUOTE) {
            b.tvWarningPost.visibility = View.VISIBLE
            b.tvWarningPost.text = getString(R.string.warning_text_quote_is_not_recommend)
        }

        b.viewPager2BottomTab.visibility = View.GONE
        // 先隐藏工具栏
        hideViewPager2()

        // 禁止用户翻页
        b.viewPager2BottomTab.isUserInputEnabled = false
//        底部工具tab
        this.bottomToolFragments = listOf(
            FragmentStateContainer(icon = R.drawable.ic_emoji_24) { PostEmojiFragment() },
            FragmentStateContainer(icon = R.drawable.ic_code_24) { PostBbsCodeFragment() },
            FragmentStateContainer(icon = R.drawable.ic_image_24) { PostAttachmentFragment.newInstance(uploadArgument, attachmentArgument) },
            FragmentStateContainer(icon = R.drawable.ic_topic_key_24) { PostTopicKeyFragment.newInstance(forumId!!) },
        )


        // 为ViewPager2设置适配器
        b.viewPager2BottomTab.adapter = object : FragmentStateAdapter(this) {
            override fun getItemCount() = bottomToolFragments.size
            override fun createFragment(position: Int) = FragmentStateContainer.newInstance(bottomToolFragments, position)
        }
        this.tabLayoutMediator = attachTabLayout(b.tabLayout, b.viewPager2BottomTab, this)
        b.tabLayout.addOnTabSelectedListener(this)

        // layout变化后延迟判断，如果输入法是打开状态，隐藏底部ViewPager2
        window.decorView.viewTreeObserver.addOnGlobalLayoutListener {
            uiDelayed(200) { if (isShowing()) hideViewPager2() }
        }

        // 关闭工具窗口
        b.ivDown.setOnClickListener {
            this.b?.etTitle?.also { InputMethodUtils.hide(it, this) }
            this.b?.etContent?.also { InputMethodUtils.hide(it, this) }
            hideViewPager2()
        }

        // 执行准备请求
        prepare()

    }

    override fun handleMessage(msg: Message): Boolean {
        when (msg.what) {
            HandlerMessageWhat.POST_ADD_TEXT_TO_CONTENT.ordinal -> {
                val m = msg.obj as? PostAddTextModel ?: return super.handleMessage(msg)
                addTextToContent(m.textBeforeSelection, m.textAfterSelection)
                return true
            }
            // 点击表情图标时，插入表情
            HandlerMessageWhat.ON_CLICK_EMOJI.ordinal -> {
                val genericEmojiModel = msg.obj as? GenericEmojiModel ?: return super.handleMessage(msg)
                val code = genericEmojiModel.code ?: return super.handleMessage(msg)
                addTextToContent(code)

                // 更新表情使用次数
                val dao = App.INSTANCE.database.emojiHistoryDao()
                val entity = dao.get(code) ?: EmojiHistory(genericEmojiModel)
                dao.add(entity.plus())
                return true
            }
            // 点击上传的图片时，插入图片代码
            HandlerMessageWhat.ON_CLICK_ATTACHMENT.ordinal -> {
                val iAttach = msg.obj as IAttach
                val thumbs = iAttach.getImageThumbs()
                // 选择倒数第二个缩略图作为bbsCode添加
                val thumb = if (thumbs.size >= 2) thumbs[thumbs.size - 2] else ImageThumb.ORIGINAL
                // 来源标注信息
                val source = when (iAttach) {
                    is UploadBody -> iAttach.error
                    is AttachmentModel -> iAttach.source
                    else -> ""
                }
                // bbsCode
                val code = iAttach.getBbsCode(thumb)
                // 如果来源信息不为空，添加到代码前面
                val text = if (source.isNullOrEmpty()) code else "[quote]${source}\n${code}[/quote]"
                addTextToContent(text)
                return true
            }
            // 已删除附件, 从正文中移除对该附件的所有引用
            HandlerMessageWhat.ON_DELETED_ATTACHMENT.ordinal -> {
                val iAttach = msg.obj as IAttach
                val thumbs = iAttach.getImageThumbs()
                val et = this.b?.etContent ?: return super.handleMessage(msg)
                // 需要删除的code
                val needDeleted = thumbs.mapNotNull { iAttach.getBbsCode(it) }

                needDeleted.forEach {
                    var index = et.text.indexOf(it)
                    while (index > -1) {
                        et.text.replace(index, index + it.length, "")
                        index = et.text.indexOf(it)
                    }
                }
            }
            // 点击主题分类之后，在标题中添加 payload
            HandlerMessageWhat.ON_CLICK_TOPIC_KEY.ordinal -> {
                val text = msg.obj as String
                b?.etTitle?.text?.insert(0, text)
            }

            // 同步附件列表
            HandlerMessageWhat.SYNC_UPLOAD_BODY.ordinal -> {
                @Suppress("UNCHECKED_CAST")
                this.attachments = msg.obj as List<UploadBody>
                return true
            }
        }

        return super.handleMessage(msg)
    }

    override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
        menuInflater.inflate(R.menu.post, menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            // 发帖
            R.id.mi_send_post -> sendPost()
            // 修改发帖参数
            R.id.mi_setting -> {
                // 弹窗选择参数
                val db = DialogPostOptionBinding.inflate(LayoutInflater.from(this))
                // 按照参数修改初始状态

                // 单贴开关仅在新主题时可用
                db.swPostOptionReplyOnce.isEnabled = argument.action == Action.NEW
                // 同步动态开关仅在回复引用时可用
                db.swPostOptionSyncDynamics.isEnabled = argument.action == Action.REPLY || argument.action == Action.QUOTE
                // 匿名开关在编辑时不可用
                db.swPostOptionAnonymous.isEnabled = argument.action != Action.MODIFY

                // 初始状态
                db.swPostOptionAnonymous.isChecked = postParamBuilder.anony == true
                db.swPostOptionHidden.isChecked = postParamBuilder.hidden == Hidden.HIDDEN
                db.swPostOptionReplyOnce.isChecked = postParamBuilder.replyOnce == true
                db.swPostOptionSyncDynamics.isChecked = postParamBuilder.option?.contains(PostOption.OPT_REPLY_FOLLOW_PUSH) == true

                AlertDialogUtils.builder(this, title = "发帖选项", contentView = db.root, listener = { _, which ->
                    //  如果点击确认，对应修改参数
                    if (which == DialogInterface.BUTTON_POSITIVE) {
                        postParamBuilder.anony = db.swPostOptionAnonymous.isChecked
                        postParamBuilder.hidden = if (db.swPostOptionHidden.isChecked) Hidden.HIDDEN else Hidden.CANCEL
                        postParamBuilder.replyOnce = db.swPostOptionReplyOnce.isChecked

                        val options = postParamBuilder.option?.toMutableList() ?: mutableListOf()
                        if (db.swPostOptionSyncDynamics.isChecked) options.add(PostOption.OPT_REPLY_FOLLOW_PUSH)
                        else options.remove(PostOption.OPT_REPLY_FOLLOW_PUSH)
                        postParamBuilder.option = options
                    }
                }).show()

            }
        }
        return true
    }

    /**
     * 正式发帖
     */
    private fun sendPost() {
        if (sending) {
            handler?.toast("正在提交,请稍等...")
            return
        }
        sending = true
        val b = this.b ?: return

        // 发送回复
        val params = postParamBuilder.also {
            // 标题
            it.title = b.etTitle.text.toString()
            // 正文
            it.content = b.etContent.text.toString().let { c -> replacePostContent(c) }
            // 附件，去掉第一个空body
            it.attachments = attachments?.let { l -> l.subList(1, l.size) }
        }.build()

        api.sendPost(
            action = argument.action.toPostAction(),
            topicId = argument.topicId,
            replyId = argument.replyId,
            colTid = argument.colTid,
            forumId = argument.forumId,
            comment = if (argument.isComment) 1 else null,
            postParam = params
        ).enqueue(object : NgaCallback<Nothing> {
            override fun onSuccess(call: Call<NgaResponse<Nothing>>, response: Response<NgaResponse<Nothing>>, body: NgaResponse<Nothing>?, data: Nothing?) {
                sending = false

                flagSuccess = true

                // 发送提示
                body?.message?.message?.also { handler?.toastLong(it) }

                // 跳转目标
                body?.message?.getLocation()?.also { loc -> setResult(200, Intent().also { it.putExtra(PostResult::class.java.simpleName, PostResult(argument.action, loc)) }) }
                // 返回
                finish()
            }

            override fun onError(call: Call<NgaResponse<Nothing>>, response: Response<NgaResponse<Nothing>>, body: NgaResponse<Nothing>?, errorMessage: String) {
                sending = false
                handler?.toastLong(errorMessage)
            }

            override fun onFailure(call: Call<NgaResponse<Nothing>>, t: Throwable) {
                sending = false
                super.onFailure(call, t)
            }
        })


    }


    private fun prepare() {
        api.prepare(
            action = argument.action.toPostAction(),
            topicId = argument.topicId,
            replyId = argument.replyId,
            colTid = argument.colTid,
            forumId = argument.forumId,
            comment = if (argument.isComment) 1 else null,
        ).enqueue(object : NgaCallback<PrepareBody> {
            override fun onSuccess(call: Call<NgaResponse<PrepareBody>>, response: Response<NgaResponse<PrepareBody>>, body: NgaResponse<PrepareBody>?, data: PrepareBody?) {
                onPrepared(data)
            }

            override fun onError(call: Call<NgaResponse<PrepareBody>>, response: Response<NgaResponse<PrepareBody>>, body: NgaResponse<PrepareBody>?, errorMessage: String) {
                // 准备失败
                if (response.code() / 10 == 5) toastLong("${response.code()}:${errorMessage}")
                else toastLong(errorMessage)
                // 延迟退出
                uiDelayed(2000) { finish() }
            }
        })
    }

    /**
     * 准备完成
     * @param prepareBody PrepareBody?
     */
    private fun onPrepared(prepareBody: PrepareBody?) {
        Log.i(TAG, "回复准备")
        val data = prepareBody ?: throw RuntimeException("准备结果为空")
        //  上传附件用到的参数
        this.uploadArgument = UploadArgument(data.attachUrl!!, data.auth!!, data.forumId!!)
        // 已有附件参数
        this.attachmentArgument = AttachmentArgument(data)

        this.forumId = data.forumId
        // 发帖参数构造器
        this.postParamBuilder = PostParamBuilder().also {
            // 当action为编辑时，标记是否编辑超时, 超时的正文内容将被添加到原文后方
            it.modifyAppend = data.modifyAppend
            // 当前是否隐藏
            it.hidden = data.hidden
        }

        // 操作界面
        val b = this.b ?: return
        b.viewPager2BottomTab.visibility = View.VISIBLE
        ui {
            // 设置Toolbar标题
            setToolbarTitle(if (argument.isComment) data.replyId?.let { "评论:$it" } ?: "评论" else when (data.action) {
                // 版面或合集名称
                PostAction.NEW -> "新帖:${data.forum?.forumName ?: data.topicCol?.title}"
                PostAction.REPLY -> data.replyId?.let { "回复:$it" } ?: "回复"
                PostAction.QUOTE -> data.replyId?.let { "引用:$it" } ?: "引用"
                PostAction.MODIFY -> data.replyId?.let { "编辑:$it" } ?: "编辑"
                null -> throw RuntimeException("action异常")
            })


            // 设置UI可用
            listOf(b.etTitle, b.etContent).forEach { it.isEnabled = true }

            // 显示工具栏顶部
            b.tabLayout.visibility = View.VISIBLE
            // 标题
            b.etTitle.setText(data.title)

            // 如果超过编辑时限，显示警告，否则将预设内容添加到编辑框
            if (data.modifyAppend == true) {
                b.tvWarningPost.visibility = View.VISIBLE
                b.tvWarningPost.text = getString(R.string.warning_text_edit_time_out)
            } else {
                val text = data.content
                    ?.let { replace1024(it) }
                    ?.let { replaceQuote(it) }
                    ?.let { replaceReply(it) }

                b.etContent.setText(text)
            }

            // 检查草稿，如果存在则替换标题和正文
            val dao = App.INSTANCE.database.postDraftDao()
            val uuid = obtainPostDraftUuid(argument)
            dao.get(uuid)?.also { draft ->
                draft.content.takeIf { it.isNotEmpty() }?.also {
                    b.etTitle.setText(draft.title)
                    b.etContent.setText(it)
                }
            }

            // 获取焦点，启动输入法，如果是new操作则焦点对象为标题，否则为正文
            (if (argument.action == Action.NEW) b.etTitle else b.etContent).also {
                it.requestFocus()
                // 如果非空，光标跳转到末尾
                if (it.text.isNotEmpty()) it.setSelection(it.text.length)
                InputMethodUtils.show(it, this)
            }
        }

    }

    /**
     * 解析意图
     * @param intent Intent?
     */
    override fun handleIntent(intent: Intent) {
        this.argument = parseArgument(intent, KEY_ARGUMENT, PostPrepareArgument::class.java) { PostPrepareArgument.parseUrl(it) }
    }

    @Parcelize
    data class PostResult(
        val action: Action,
        val forumId: Long? = null,
        val topicId: Long? = null,
        val replyId: Long? = null,
        val page: String? = null,
    ) : Parcelable {
        constructor(action: Action, ngaLocation: NgaLocation) : this(
            action = action,
            forumId = ngaLocation.forumId,
            topicId = ngaLocation.topicId,
            replyId = ngaLocation.replyId,
            page = ngaLocation.page,
        )
    }


    override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
        this.bottomToolFragments[position].icon?.also { tab.setIcon(it) }
    }

    /**
     * 显示ViewPager2，关闭输入法
     */
    private fun showViewPager2() {
        val b = this.b ?: return
        // 关闭输入法
        InputMethodUtils.hide(b.etTitle, this)
        InputMethodUtils.hide(b.etContent, this)
        // 显示viewPager2

        val vp2 = this.b?.viewPager2BottomTab ?: return
        vp2.layoutParams = ConstraintLayout.LayoutParams(vp2.layoutParams).also {
            it.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
            it.topToBottom = ConstraintLayout.LayoutParams.UNSET
        }
    }

    /**
     * 隐藏ViewPager2
     */
    private fun hideViewPager2() {
        Log.i(TAG, "隐藏ViewPager2")
        val vp2 = this.b?.viewPager2BottomTab ?: return

        val layoutParams = vp2.layoutParams as? ConstraintLayout.LayoutParams ?: return
        // 如果已经隐藏，停止
        if (layoutParams.bottomToBottom == ConstraintLayout.LayoutParams.UNSET) return

        vp2.layoutParams = layoutParams.also {
            it.bottomToBottom = ConstraintLayout.LayoutParams.UNSET
            it.topToBottom = ConstraintLayout.LayoutParams.PARENT_ID
        }
    }

    override fun onTabSelected(tab: TabLayout.Tab?) {
        showViewPager2()
    }

    override fun onTabUnselected(tab: TabLayout.Tab?) {
    }

    override fun onTabReselected(tab: TabLayout.Tab?) {

        showViewPager2()
    }

    /**
     * 判断当前输入法是否开启
     * @return Boolean
     */
    private fun isShowing(): Boolean {
        // 获取当前屏幕内容的高度
        val screenHeight = window.decorView.height

        // 获取View可见区域的bottom
        val rect = Rect()
        window.decorView.getWindowVisibleDisplayFrame(rect)
        return screenHeight * 3 > rect.bottom * 4
    }

    /**
     * 向正文框当前位置插入文本
     * @param textBeforeSelection 向选中位置之前插入的文本
     * @param textAfterSelection 向选中位置之后插入的文本
     */
    private fun addTextToContent(textBeforeSelection: String? = null, textAfterSelection: String? = null) {
        val et = this.b?.etContent ?: return
        // 当前文本
        val text = et.text
        // 插入后方文本
        val end = et.selectionEnd
        val start = et.selectionStart
        textAfterSelection?.also { text.insert(end, it) }
        // 插入前方文本
        textBeforeSelection?.also { text.insert(start, it) }
        // 重新设置选中范围
        val length = textBeforeSelection?.length ?: 0
        et.setSelection(start + length, end + length)
    }


    companion object {
        /**
         * 正文长度限制
         * - 引用模板内容超过该限制时，如果其中存在未关闭折叠，补充关闭，不存在时添加折叠
         * - 当回复内容超过该限制时，自动添加折叠
         */
        private const val CONTENT_LIMIT = 250
        private const val COLLAPSE_START = "[collapse"
        private const val COLLAPSE_END = "[/collapse]"
        private val TAG = PostActivity::class.java.simpleName
        private val PATTEN_REPLACE_1024: Pattern = Pattern.compile("\\[uid.+?].*?(1024).*?\\[/uid]")
        private val PATTEN_REPLACE_QUOTE: Pattern = Pattern.compile("\\[b]Post by .+?\\[/b]\n\n([\\s\\S]+)\\[/quote]")
        private val PATTEN_REPLACE_REPLY: Pattern = Pattern.compile("\\[b]Reply to.+?\\[/b]")
        private val PATTEN_REPLACE_QUOTE_PAIR: Pattern = Pattern.compile("\\[quote][\\s\\S]+?\\[/quote]")
        const val KEY_ARGUMENT = "ARGUMENT_POST_PREPARE"

        /**
         * 删除用户名中的1024
         * @param content String?
         * @return String?
         */
        fun replace1024(content: String?) = content?.replace(PATTEN_REPLACE_1024.toRegex()) { matchResult ->
            matchResult.value.replace("1024", "")
        }

        /**
         * 如果正文含有引用模板，且长度超出限制，则进行处理
         * @param content String?
         * @return String?
         */
        fun replaceQuote(content: String?) = content?.replace(PATTEN_REPLACE_QUOTE.toRegex()) { result ->
            val text = result.value
            val group = result.groupValues[1]
            when {
                // 长度小于限制时，不做处理
                group.length < CONTENT_LIMIT -> text
                // 含有未关闭折叠时，补充关闭
                group.contains(COLLAPSE_START) && !group.contains(COLLAPSE_END) -> text.replace(group, "$group$COLLAPSE_END")
                // 添加折叠
                else -> text.replace(group, "$COLLAPSE_START=引用内容已折叠]$group$COLLAPSE_END")
            }
        }

        /**
         * 如果正文含有回复模板，破坏模板
         * @param content String?
         * @return String?
         */
        fun replaceReply(content: String?) = content?.replace(PATTEN_REPLACE_REPLY.toRegex()) { result ->
            result.value.replace("(", "").replace(")", "")
        }

        /**
         * 如果发送的正文长度超过限制，自动添加引用框
         * @param content String?
         * @return String?
         */
        fun replacePostContent(content: String?) = content?.let { rawText ->
            when {
                // 如果开关关闭 不做处理
                !GlobalProperty.getInstance().autoQuoteContent -> rawText
                // 如果原文不超过限制 不做处理
                rawText.length < CONTENT_LIMIT -> rawText
                else -> {
                    // 筛选模板和引用框以外的部分
                    val countText = rawText
                        .replace(PATTEN_REPLACE_REPLY.toRegex(), "")
                        .replace(PATTEN_REPLACE_QUOTE_PAIR.toRegex(), "")
                    //  如果筛选部分长度超过限制，则在最外层添加引用
                    if (countText.length < CONTENT_LIMIT) rawText else "[quote]\n$rawText\n[/quote]"
                }
            }

        }

        /**
         * 获取发帖uuid
         * @param argument PostPrepareArgument
         * @return String
         */
        fun obtainPostDraftUuid(argument: PostPrepareArgument) = "${App.INSTANCE.account.userId}_${argument}"

        /**
         * 获取意图
         * @param context Context
         * @param argument PostPrepareArgument
         * @return Intent
         */

        fun obtainIntent(context: Context, argument: PostPrepareArgument) = Intent(context, PostActivity::class.java).also { it.putExtra(KEY_ARGUMENT, argument) }
    }
}